package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.system.config.properties.EmailVerificationCodeProperties;
import com.ruoyi.system.dto.DeserializableMailMessage;
import com.ruoyi.system.service.ISysEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@Service
public class SysEmailServiceImpl implements ISysEmailService {

    /**
     * 发送邮件的工具
     */
    @Autowired
    private JavaMailSender javaMailSender;

    /**
     * 发邮件的账户
     */
    @Value("${spring.mail.username}")
    private String myAccount;

    /**
     * 访问 Redis
     */
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 邮件验证码相关配置
     */
    @Autowired
    private EmailVerificationCodeProperties emailVerificationCodeProperties;

    @Override
    public String generateCodeKey() {
        return this.emailVerificationCodeProperties.getCodesKeyPrefix() + ":" + ShiroUtils.getSysUser().getEmail();
    }

    @Override
    public void willSendVerificationCode() {
        SysUser user = ShiroUtils.getSysUser();

        if (user.getEmail() == null || user.getEmail().isEmpty()) {
            throw new ServiceException("您上未绑定邮箱，无法发送");
        }

        //生成验证码
        int verificationCode = ThreadLocalRandom.current().nextInt(100000, 999999);

        //缓存验证码
        String codeKey = this.generateCodeKey();
        Boolean keyIsAbsent = this.redisTemplate.opsForValue().setIfAbsent(codeKey, verificationCode, this.emailVerificationCodeProperties.getCodeExpiry(), TimeUnit.MINUTES);

        if (!keyIsAbsent) {
            throw new ServiceException("验证码已发送，如无法收到，请联系管理员");
        }

        //封装邮件
        StringBuilder subject = new StringBuilder("若依科技：");
        subject.append("亲爱的").append(user.getUserName()).append("用户，");
        subject.append("您正在进行重要操作，请进行安全验证，下面是您的验证码。如非本人操作，请忽略。");

        StringBuilder text = new StringBuilder();
        text.append("您的验证码是").append(verificationCode).append("，");
        text.append("请不要将验证码转发给他人。\r\n");
        text.append("有效期").append(this.emailVerificationCodeProperties.getCodeExpiry()).append("分钟。");

        DeserializableMailMessage message = new DeserializableMailMessage();
        message.setFrom(this.myAccount);
        message.setTo(user.getEmail());
        message.setSubject(subject.toString());
        message.setText(text.toString());

        //提交发送任务
        this.redisTemplate.opsForSet().add(this.emailVerificationCodeProperties.getTasksKey(), message);
    }

    @Override
    public void send(SimpleMailMessage message) {
        this.javaMailSender.send(message);
    }

    @Override
    public boolean checkVerificationCode(Integer verificationCode) {
        if (verificationCode == null) {
            return false;
        }

        Object value = this.redisTemplate.opsForValue().get(this.generateCodeKey());
        return value != null && value.equals(verificationCode);
    }

}
